package com.chisheng.caa.util;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.Objects;

/**
 * JWT 工具类。
 *
 * @author Chisheng Chen
 */
public final class JwtUtil {

    /**
     * 有效载荷 KEY
     */
    public static final String CLAIM_KEY = "ID";

    /**
     * TOKEN 请求头 KEY
     */
    public static final String TOKEN_HEADER = "caa-access-token";

    /**
     * TOKEN 过期时间
     */
    public static final long EXPIRY = 1000 * 60 * 60 * 24;

    /**
     * 密钥
     */
    private static final String SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";

    private JwtUtil() {
        throw new UnsupportedOperationException();
    }

    /**
     * 生成 TOKEN
     */
    public static String createToken(final Object id) {
        return Jwts.builder()
                .setId(IdUtil.fastSimpleUUID())
                .setHeaderParam("typ", "JWT")
                /* 加密算法 */
                .setHeaderParam("alg", "HS256")
                /* 主题 */
                .setSubject("caa")
                .setIssuer("caa")
                /* 签发时间 */
                .setIssuedAt(new Date())
                /* 设置过期时间 */
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRY))
                /* Token 有效载荷 */
                .claim(CLAIM_KEY, Objects.requireNonNull(id).toString())
                /* Token 签名 */
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .compact();
    }

    /**
     * TOKEN 是否存在与有效
     */
    public static boolean isValidToken(final String token) {
        try {
            if (ObjectUtil.isEmpty(token)) {
                return false;
            }

            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (Exception ignored) {
            return false;
        }
    }

    /**
     * 根据 TOKEN 获取有效载荷
     */
    public static Object parseToken(final String token) {
        if (ObjectUtil.isEmpty(token) || !isValidToken(token)) {
            return null;
        }

        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
        return claimsJws.getBody().get(CLAIM_KEY);
    }

}